package org.cn.osiris.basic.service.impl;

import org.cn.osiris.basic.domain.SmsCodeDto;
import org.cn.osiris.basic.domain.VerifyCodeConstants;
import org.cn.osiris.basic.dto.CodeDto;
import org.cn.osiris.basic.exception.BusinessException;
import org.cn.osiris.basic.service.IVerifyCodeService;
import org.cn.osiris.basic.util.StrUtils;
import org.cn.osiris.basic.util.VerifyCodeUtils;
import org.cn.osiris.user.domain.User;
import org.cn.osiris.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImageVerifyCode(String key) {
        //调用图形工具类生成图形验证码
        String imageCode = StrUtils.getComplexRandomString(4);

        //将key和图形验证码保存在redis中，并设置过期时间
        redisTemplate.opsForValue().set(key,imageCode,1, TimeUnit.MINUTES);

        //调用工具类，将图形验证码写到图片上，并生成Base64编码的字符串
        String verifyCode = VerifyCodeUtils.verifyCode(115, 40, imageCode);

        System.out.println(verifyCode);
        //返回Base64编码的字符串
        return verifyCode;
    }

    /**
     * 短息验证业务
     * @param smsCodeDto
     */
    @Override
    public void sendSmsCode(SmsCodeDto smsCodeDto) {
        //1.校验 - 空值校验
        System.out.println(smsCodeDto);
        String imageCode = smsCodeDto.getImageCode();
        String imageCodeKey = smsCodeDto.getImageCodeKey();
        String phone = smsCodeDto.getPhone();
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }
        if(StringUtils.isEmpty(imageCode)){
            throw new BusinessException("图片验证码不能为空");
        }
        if(StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请刷新页面重新获取图片验证码");
        }


        //2.校验 - 手机号是否被注册 - 查询t_user表
        User user = userMapper.findByPhone(phone);
        if(user != null){
            throw new BusinessException("该手机已经注册，请直接登录!");
        }
        //3.校验 - 图片验证码校验
            //3.1.图片验证码是否过期
        Object imageCodeValue = redisTemplate.opsForValue().get(imageCodeKey);
        if(imageCodeValue == null){
            throw new BusinessException("图片验证码过期，请重新输入");
        }
            //3.2.图片验证码是否正确
        if(!imageCodeValue.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("错误的图片验证码，请重新输入");
        }

        //4.判断原来的验证码是否有效【3分钟过期 - redis】，从redis是否能拿到通过key【register:18708146200】
            //4.1.如果拿到了，表示有效,继续判断是否过了1分钟重发时间 value【9527:14688777777711】
                //4.1.1.如果没有过，就不应该再发，提示错误 - 请勿重发验证码
                //4.1.2.如果过了，就使用上次的验证码，但是要刷新过期时间【重新添加resis，用新的时间戳】
            //4.2.如果没有拿到，表示验证码过期了
                //4.2.1.重新生成验证码，并添加到redis
        Object codeObj = redisTemplate.opsForValue().get(VerifyCodeConstants.REGISTER_CODE_PREFIX + phone);

        String code = null;
        if (codeObj != null){
            //如果没有过期
            String codeStr = (String) codeObj;
            String time = codeStr.split(":")[1];
            Long intervalTime = System.currentTimeMillis() - Long.valueOf(time) ;

            if (intervalTime<=1*60*1000){
                //时间没过时
                throw  new BusinessException("请勿重复发送!");
            }else{
                 code = codeStr.split(":")[0];
            }

        }else{
            code = StrUtils.getComplexRandomString(6);
        }
        //存3分钟
        redisTemplate.opsForValue().set(VerifyCodeConstants.REGISTER_CODE_PREFIX+phone,code+":"+System.currentTimeMillis(),5, TimeUnit.MINUTES);

        //5.调用短信接口发送短信
        //SmsUtil.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");//可以这样测试
    }

    @Override
    public void binderVerifyCode(CodeDto codeDto) {
        //1.校验 - 空值校验

        String phone = codeDto.getPhone();

        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }


        //2.校验 - 手机号是否被注册 - 查询t_user表
        User user = userMapper.findByPhone(phone);
        if(user != null){
            throw new BusinessException("该手机已经注册，请直接登录!");
        }

        //4.2.1.从redis中拿取到手机验证码， key【业务🗡:手机号】
        Object phoneCode = redisTemplate.opsForValue().get("binder:" + phone);
        String code = null;
        if (phoneCode != null){
            //如果没有过期
            //处理时间戳
            String codeStr = (String) phoneCode;
            String time = codeStr.split(":")[1];
            Long intervalTime = System.currentTimeMillis() - Long.valueOf(time) ;
            //判断时间戳是否过期
            if (intervalTime<=1*60*1000){
                //时间没过时
                throw  new BusinessException("请勿重复发送!");
            }else{
                code = codeStr.split(":")[0];
            }

        }else{
            //生成六位随机纯数字
            code = StrUtils.getComplexRandomString(6);
        }
        //存3分钟
        redisTemplate.opsForValue().set("binder"+phone,code+":"+System.currentTimeMillis(),5, TimeUnit.MINUTES);

        //5.调用短信接口发送短信
        //SmsUtil.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        //可以这样测试
        System.out.println("你的验证码为：" + code + "，请在5分钟之内使用!");
    }
}
